#include <iostream>
#include <string>
#include <ctime>
#include "Sock.hpp"
#include "Protocol.hpp"

// 客户端调用
void Send(int sock, const std::string& sendStr)
{
    int n = send(sock, sendStr.c_str(), sendStr.size(), 0);
    if(n != sendStr.size())
       std::cerr << "Send Error" << std::endl; 
}

// 客户端调用
bool Recv(int sock, std::string& out)
{
    char buffer[1024];
    while(true)
    {
        ssize_t n = recv(sock, buffer, sizeof(buffer) - 1, 0);
        if(n > 0)
        {
            buffer[n] = 0;
            out += buffer;
        }
        else if(n == 0)
        {
            return false;
        }
        else
        {
            if(errno == EAGAIN || errno == EWOULDBLOCK)
            {
                if(out.empty()) continue; // 如果没有收到响应，则继续对应 recv 函数
                return true;
            }
            else if(errno == EINTR)
            {
                continue;
            }
            else
            {
                std::cerr << "Recv Error" << std::endl;
                return false;
            }
        }
    }
}

static void Usage(char* proc)
{
    std::cout << "\nUsage: " << proc << "serverIp serverPort" << std::endl;
}

// 网络版计算器客户端
// int main(int argc, char* argv[])
// {
//     srand((unsigned)time(nullptr));
//     if(argc != 3)
//     {
//         Usage(argv[0]);
//         exit(1);
//     }

//     int sock = Sock::Socket();
//     if(!Sock::Connect(sock, std::string(argv[1]), atoi(argv[2])))
//     {
//         std::cerr << "Connect Error: " << errno << " " << strerror(errno) << std::endl; 
//     }

//     const char* op = "+-*/%#";
//     Sock::SetNonBlock(sock);
//     std::string buffer;
//     while(true)
//     {
//         Request req;
//         // req._x = rand() % 100;
//         // req._y = rand() % 100;
//         // req._op = op[rand() % 6];
//         std::cout << "Please Enter x: ";
//         std::cin >> req._x;
//         std::cout << "Please Enter op: ";
//         std::cin >> req._op;
//         std::cout << "Please Enter y: ";
//         std::cin >> req._y;
//         // 序列化
//         std::string sendStr = req.Serialize();
//         sendStr = Encode(sendStr);
//         // 发送请求
//         Send(sock, sendStr);
//         // 非阻塞读取全部数据
//         bool ret = Recv(sock, buffer);
//         if(!ret) break; // 服务器关闭连接或者Recv出错了

//         std::string package = Decode(buffer);
//         if(package.empty()) continue;
//         // 接收到了一个完整的报文
//         Response resp;
//         resp.Deserialized(package);
//         std::string err;
//         switch(resp._code)
//         {
//             case 1:
//                 err = "Division By Zero Error";
//                 break;
//             case 2:
//                 err = "Modular Division By Zero Error";
//                 break;
//             case 3:
//                 err = "Operation Error";
//                 break;
//             default:
//                 std::cout << "Calculation Result: " << resp._ret << std::endl;
//                 break;
//         }
//         if(!err.empty()) std::cout << err << std::endl;
//     }
//     close(sock);

//     return 0;
// }

int main(int argc, char* argv[])
{
    srand((unsigned)time(nullptr));
    if(argc != 3)
    {
        Usage(argv[0]);
        exit(1);
    }

    int sock = Sock::Socket();
    if(!Sock::Connect(sock, std::string(argv[1]), atoi(argv[2])))
    {
        std::cerr << "Connect Error: " << errno << " " << strerror(errno) << std::endl; 
    }
    Sock::SetNonBlock(sock);

    std::string word;
    std::string buffer;
    while(true)
    {
        std::cout << "Please Enter The Word: ";
        std::cin >> word;
        word = Encode(word);

        Send(sock, word);
        // 非阻塞读取全部数据
        bool ret = Recv(sock, buffer);
        if(!ret) break; // 服务器关闭连接或者Recv出错了
        std::string package = Decode(buffer);
        std::cout << package << std::endl;
    }

    return 0;
}